use std::fs;
use std::path::Path;
use std::sync::Mutex;
use std::sync::OnceLock;
use std::sync::atomic::{AtomicBool, Ordering};
use time::macros::format_description;
use tokio::sync::mpsc;
use tracing::{Level, error, info, warn};
use tracing_appender::rolling::{RollingFileAppender, Rotation};
use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt};

// 定义日志消息的结构
#[derive(Debug)]
struct LogMessage {
    level: Level,
    message: String,
}

// 使用线程安全的静态变量
static LOG_SENDER: OnceLock<Mutex<Option<mpsc::UnboundedSender<LogMessage>>>> = OnceLock::new();
static INITIALIZED: AtomicBool = AtomicBool::new(false);

/// 初始化日志系统
///
/// # 参数
/// * `log_dir` - 日志文件存储目录
///
/// # 示例
/// ```
/// init_logger("logs").expect("日志初始化失败");
/// ```
pub fn init_logger<P: AsRef<Path>>(log_dir: P) -> Result<(), Box<dyn std::error::Error>> {
    // 确保只初始化一次
    if INITIALIZED.load(Ordering::SeqCst) {
        return Ok(());
    }

    // 确保日志目录存在
    fs::create_dir_all(&log_dir)?;

    // 设置按天滚动的日志文件
    let file_appender = RollingFileAppender::new(Rotation::DAILY, log_dir, "log");

    // 创建日志订阅器，使用自定义格式
    let subscriber = tracing_subscriber::registry().with(
        fmt::layer()
            .with_writer(file_appender)
            .with_ansi(false)
            // 自定义日志格式，只包含时间戳和消息内容
            .event_format(
                fmt::format()
                    // 使用本地时区（中国为UTC+8）
                    .with_timer(fmt::time::LocalTime::new(format_description!(
                        "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:3]"
                    )))
                    .with_level(true) // 是否日志级别
                    .with_target(false) // 是否显示目标模块
                    .with_thread_ids(false) // 是否显示线程ID
                    .with_thread_names(false) // 是否显示线程名称
                    .with_file(false) // 是否显示文件名
                    .with_line_number(false), // 是否显示行号
            ),
    );

    // 设置全局默认的订阅器
    subscriber.init();

    // 创建异步通道
    let (tx, mut rx) = mpsc::unbounded_channel::<LogMessage>();

    // 初始化全局发送端
    LOG_SENDER.get_or_init(|| Mutex::new(Some(tx)));
    INITIALIZED.store(true, Ordering::SeqCst);

    // 启动异步任务处理日志
    tokio::spawn(async move {
        while let Some(log_msg) = rx.recv().await {
            match log_msg.level {
                Level::INFO => info!("{}", log_msg.message),
                Level::WARN => warn!("{}", log_msg.message),
                Level::ERROR => error!("{}", log_msg.message),
                _ => info!("{}", log_msg.message),
            }
        }
    });

    Ok(())
}

/// 异步写入信息日志
#[allow(dead_code)]
pub fn log_info(message: impl Into<String>) {
    send_log(Level::INFO, message);
}

/// 异步写入警告日志
#[allow(dead_code)]
pub fn log_warn(message: impl Into<String>) {
    send_log(Level::WARN, message);
}

/// 异步写入错误日志
#[allow(dead_code)]
pub fn log_error(message: impl Into<String>) {
    send_log(Level::ERROR, message);
}

// 内部函数：发送日志消息到异步通道
fn send_log(level: Level, message: impl Into<String>) {
    if let Some(sender_mutex) = LOG_SENDER.get() {
        if let Ok(sender_guard) = sender_mutex.lock() {
            if let Some(sender) = sender_guard.as_ref() {
                let _ = sender.send(LogMessage {
                    level,
                    message: message.into(),
                });
            }
        }
    }
}
